#ifndef SOLVER_H
#define SOLVER_H

#include "../Input/PicParams.h"
#include "../Parallel/ParallelMPI.h"
#include "../Grid/Grid.h"
#include "../PhysicalField/PhysicalField.h"
#include "../Diagnostic/Diagnostic.h"
#include "../Tool/Timer.h"
#include "../Tool/Log.h"

class PhysicalField;
class Diagnostic;

// --------------------------------------------------------------------------------------------------------------------
//Class Solver
// --------------------------------------------------------------------------------------------------------------------
class Solver
{

public:
    //Creator for Solver
    Solver(PicParams* params_, ParallelMPI* pmpi_, Grid* grid_, PhysicalField* fields_, Diagnostic* diag_) :
        params(params_),
        pmpi(pmpi_),
        grid(grid_),
        fields(fields_),
        diag(diag_)
    {
        const_ephi0_inv = 1.0 / params->const_ephi0;
    };
    virtual ~Solver() {};

    //Overloading of () operator
    virtual void operator()(PhysicalField* fields)=0;
    virtual void operator()(ParallelMPI* pmpi, PhysicalField* fields, Diagnostic* diag)=0;
    virtual void solve_SLU(Field<double>* rho, Field<double>* phi){};
    virtual void finishSLU(){};
    virtual void initSLU_test(){};
    virtual void initSLU(){};
    virtual void solve_Exy(Field<double>* phi, Field<double>* Ex, Field<double>* Ey){};

    //boundary condition of electric field for Dirichlet condition
    double bc_e_value[3][2];
    //boundary condition of electric field for Neumann condition
    double bc_e_derivative[3][2];

    //reciprocal of dielectric constant
    double const_ephi0_inv;

    vector<Timer> timer_solver;

    PicParams* params;
    ParallelMPI* pmpi;
    Grid* grid;
    PhysicalField* fields;
    Diagnostic* diag;

protected:

};//END class

#endif
